<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /*
        闭包：
          1. 什么是闭包？
            通过Chrome开发工具调试查看，闭包是存在嵌套内部函数中的一个"对象", 叫做closure，内部保存引用的外部函数局部变量

            简单说：闭包是一个叫做 closure 对象，存在内部函数中，存了外部函数的局部变量
          
          2. 闭包的产生条件？

            - 函数嵌套
            - 内部函数引用外部函数局部变量
            - 调用外部函数

          3. 生命周期

            - 产生：当内部函数定义执行完成时，就产生了
            - 死亡：当内部函数成为垃圾对象时，就死亡了
              当内部函数没有变量引用，内部函数会被JS垃圾回收机制回收，内部函数中闭包也会一起死

          4. 优缺点

            - 优点（作用）
              - 延长局部变量生命周期
              - 让函数外部操作函数内部的数据

            - 缺点：
              - 不及时释放，容易导致内存泄漏
                解决方案：及时释放（内部函数成为垃圾对象）

          5. 应用（用的很少、尽量少用）
            - 防抖或节流函数中使用
            - React 高阶函数 或 高阶组件（HOC）
            - Vue响应式原理：每个响应式数据都会生成dep对象，dep对象是以闭包形式存在属性的读取（get）和设置（set）方法中
              将来读取或设置属性，dep对象方法可以触发响应式

      */
      // var b = 2;
      // function fn1() {
      //   debugger;
      //   var a = 1;
      //   function fn2() {
      //     var c = 3;
      //     console.log(a, b, c);
      //   }
      //   console.log(fn2);
      // }
      // fn1();

      // var b = 2;
      // function fn1() {
      //   debugger;
      //   var a = 1;
      //   const fn2 = function () {
      //     var c = 3;
      //     console.log(a, b, c);
      //   };
      //   console.log(fn2);
      // }
      // fn1();

      // 延长局部变量生命周期
      function fn1() {
        var a = 1;
        var obj = {};
        const fn2 = function () {
          // console.log(a);
          // 让函数外部操作函数内部的数据
          a++;
          return obj;
        };
        return fn2;
      }
      let fn2 = fn1();
      let obj = fn2();
      // fn2 = null;
    </script>
  </body>
</html>
